// ignore_for_file: avoid_print

import 'package:flujs/flujs.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flujs_jsc/jsc.dart' as jsc;
import 'package:flujs_qjs/qjs.dart' as qjs;

void main() async {
  executePromise(JSFRuntime rt) async {
    var context = rt.newContext()..loadExtension();

    // ignore: unused_local_variable
    final added = context.addInterface('callNativeAsync', (args) async {
      print('[callNativeAsync]1 $args ${args is List}');
      await Future.delayed(const Duration(seconds: 1));
      if ((args as List).isEmpty) {
        return Future.value(DateTime.now().toIso8601String());
      }
      final o = args[0];
      print('[callNativeAsync]2 $o ${o is Map}');
      if (o is Map) {
        dynamic b = o['a'];
        print('[callNativeAsync]3 ${b is num}');
        return Future.value(++b);
      }
      return Future.value(1);
    });

    try {
      final rv = await context.evalAsync('''
// console.log(this)
var global = this;
window = global;
window.onerror = function(e) {
  console.error('window.onerror: ', e)
}
if (typeof MyClass == 'undefined') {
  var MyClass = class {
constructor(id) {
  this.id = id;
}
getid() {
  return this.id;
}
  }
}
async function test() {
  // try {
  console.log('[invoke test]')
  var obj = new MyClass(1);
  var s = JSON.stringify(obj);
  console.log('[test] obj = ' + s);
  var obj2 = JSON.parse(s);
  // console.log('[test] obj2.id = ' + obj2.getid())
  var v = Math.trunc(Math.random() * 100).toString();
  console.log('[v] = ' + v);
  // var a = await callNativeAsync();
  // console.log('a = ' + a);
  var b = await callNativeAsync({a: 1});
  console.log('b = ' + b);
  return { 'a': a };
  // } catch(e) {
    // console.error('catched', e)
  // }
}

async function testWithCatch() {
  try {
return { 'a': a };
  } catch(e) {
console.error(JSON.stringify(e))
  }
}
function undef() {
  a = b / c + 1;
}
// undef();
// test();
testWithCatch()

// throw new Error('directly')

''');
      print('[rv] ${rv.toString()}');
    } catch (e) {
      print('xxx $e');
    }
  }

  // FIXME:  cannot get exception detail information in js code when exception occurred
  // FIXME: [rv] Error: ReferenceError      Can't find variable: Erroglobal code@ReferenceErrorundefinedundefined
  // FIXME: top level throw error will not trigger __onRejected.
  test('jsf_jsc_promise', () async {
    var rt = jsc.getJSFRuntime();
    await executePromise(rt);
  });

  test('jsf_qjs_promise', () async {
    var rt = qjs.getJSFRuntime();
    await executePromise(rt);
  });
}
